﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FerrScript
{
    public class ScriptCore
    {
        #region Fields
        internal Dictionary<string, ScriptVariable> executionVariables;
        #endregion

        #region Properties
        public object this[string aVariableName]
        {
            get 
            {
                if (!HasVariable(aVariableName))
                    return null;
                return executionVariables[aVariableName].value.value; 
            }
            set 
            {
                // add this one in if it didn't exist
                if (!HasVariable(aVariableName))
                {
                    ScriptVariable var = new ScriptVariable();
                    var.indent  = 0;
                    var.alive   = true;
                    var.varName = aVariableName;
                    executionVariables.Add(aVariableName, var);
                }
                
                executionVariables[aVariableName].value = new ScriptValue(value); 
            }
        }
        #endregion

        #region Constructors
        internal ScriptCore(ScriptVariable[] aVariables)
        {
            executionVariables = new Dictionary<string, ScriptVariable>(aVariables.Length);
            for (int i = 0; i < aVariables.Length; i++)
            {
                if (aVariables[i].alive)
                    executionVariables.Add(aVariables[i].varName, aVariables[i]);
            }
        }
        internal ScriptCore(ScriptCore aOther)
        {
            Copy(aOther);
        }
        #endregion

        #region Methods
        /// <summary>
        /// Checks to see if the given variable exists within this ScriptCore
        /// </summary>
        /// <param name="aVarName">The variable to check for</param>
        /// <returns>If it is within this ScriptCore</returns>
        public bool HasVariable(string aVarName)
        {
            return (executionVariables.ContainsKey(aVarName));
        }
        /// <summary>
        /// This will add a root level variable with the given name into the script, or set the value of that variable.
        /// If you're trying to set the variable, you can also use the '[]' operator
        /// </summary>
        /// <param name="aVarName">Name of the variable</param>
        /// <param name="aValue">Initial value for the variable</param>
        public void AddVariable(string aVarName, object aValue)
        {
            this[aVarName] = aValue;
        }
        /// <summary>
        /// Returns the value of the variable, or null if it doesn't exist
        /// </summary>
        /// <param name="aVarName">Name of the variable you're looking for</param>
        /// <returns>The value of the variable, or null if it doesn't exist</returns>
        public object GetVariable(string aVarName)
        {
            return this[aVarName];
        }
        internal void Copy(ScriptCore aOther)
        {
            if (executionVariables == null)
            {
                executionVariables = new Dictionary<string,ScriptVariable>();
                foreach (KeyValuePair<string, ScriptVariable> kvp in aOther.executionVariables)
                {
                    ScriptVariable var = new ScriptVariable();
                    var.indent  = kvp.Value.indent;
                    var.alive = kvp.Value.alive;
                    var.varName = kvp.Value.varName;
                    var.value = kvp.Value.value;

                    executionVariables.Add(var.varName, var);
                }
            }
            else
            {
                foreach (KeyValuePair<string, ScriptVariable> kvp in executionVariables)
                {
                    kvp.Value.value = aOther.executionVariables[kvp.Value.varName].value;
                }
            }
        }
        #endregion
    }
}

